//! dfs 监视器命令实现

use std::sync::Arc;

use monitor::{CompleterPosFrom, CompleterSuggestion, Monitor};

use self::{
    cat::monitor_command_cat_register, cd::monitor_command_cd_register,
    close::monitor_command_close_register, echo::monitor_command_echo_register,
    fdinfo::monitor_command_fdinfo_register, ls::monitor_command_ls_register,
    open::monitor_command_open_register, pwd::monitor_command_pwd_register,
    read::monitor_command_read_register, seek::monitor_command_seek_register,
    write::monitor_command_write_register,
};
use crate::{
    inode::{link_path_walk, DfsInode},
    path::DfsPath,
};

mod cat;
mod cd;
mod close;
mod echo;
mod fdinfo;
mod ls;
mod open;
mod pwd;
mod read;
mod seek;
mod write;

/// 注册 dfs 实现监视器命令
pub fn dfs_monitor_registers(mon: &Monitor) {
    monitor_command_cat_register(mon);
    monitor_command_cd_register(mon);
    monitor_command_close_register(mon);
    monitor_command_echo_register(mon);
    monitor_command_fdinfo_register(mon);
    monitor_command_ls_register(mon);
    monitor_command_open_register(mon);
    monitor_command_pwd_register(mon);
    monitor_command_read_register(mon);
    monitor_command_seek_register(mon);
    monitor_command_write_register(mon);
}

pub(crate) fn mon_command_completer(
    arg: Option<&&str>,
    is_cd: bool,
    is_space: bool,
) -> Option<CompleterSuggestion> {
    let parent_inode;
    let path;
    let mut file = None;
    if is_space {
        parent_inode = link_path_walk(".").unwrap();
    } else {
        path = DfsPath::new(arg.unwrap());
        file = path.file_name();
        let dir1 = if file.is_some() { path.parent() } else { Some(path) };
        if let Some(d) = dir1 {
            parent_inode = link_path_walk(d.to_str().unwrap())?;
        } else {
            parent_inode = link_path_walk(".").unwrap();
        }
    }

    let mut v = Vec::new();
    let completer_process = |inode: &Arc<DfsInode>, is_cd, v: &mut Vec<String>| {
        if is_cd && inode.is_dir() {
            v.push(inode.name().clone() + "/");
        } else if !is_cd {
            if inode.is_dir() {
                v.push(inode.name().clone() + "/");
            } else {
                v.push(inode.name().clone());
            }
        }
    };
    let mut pos = 0;
    if let Some(f) = file {
        // 同样的, 处理 "."/".." 特殊情况
        if f == "." {
            v.push(".".to_string());
            v.push("..".to_string());
            pos -= 1;
        } else if f == ".." {
            v.push("/".to_string());
        } else {
            parent_inode.for_each_childs(|inode| {
                if inode.name().starts_with(f.as_str()) {
                    completer_process(inode, is_cd, &mut v);
                }
            });
            pos -= f.len() as isize;
        }
    } else {
        parent_inode.for_each_childs(|inode| {
            completer_process(inode, is_cd, &mut v);
        });
    }

    let deal_one = v.len() == 1 && !v[0].ends_with('/');
    v.sort();
    Some(CompleterSuggestion::create(CompleterPosFrom::Current(pos), v, deal_one))
}
